/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkGbMediaServer.h"
#include "MkEvent/MkEventPool.h"
#include "MkGbStreamSource.h"
#include "MkRtp/MkRtpTcpClient.h"
#include "MkEvent/MkEvent.h"
#include "MkGbConsumer.h"
#include "MkSdp/MkSdp.h"
#include "MkUtil/MkUtil.h"
#include "MkUtil/MkLog.h"
#include "MkEvent/MkTimer.h"
#include "MkRtp/MkRtpServerPool.h"
#include "MkRtp/MkRtpTcpServer.h"
#include "MkRtp/MkRtpUdpServer.h"
#include "MkUtil/MkMd5.h"
#include "MkPs/MkPsMuxer.h"

CMkGbMediaServer::CMkGbMediaServer(CMkEventPool* pEventPool, CMkTimer* pTimer, CMkRtpServerPool* pRtpPool, const MkGbRegServerStateChangeCallback& RegStateChangeCb, const MkMediaCallbacks& MediaCallbacks)
    : CMkGb28181(pEventPool, pTimer)
    , m_MediaCbs(MediaCallbacks)
    , m_pRtpPool(pRtpPool)
    , m_RegStateChangeCb(RegStateChangeCb)
    , m_RegSuccess(FALSE)
{

}

Uint32 CMkGbMediaServer::Start(const MkGbStartParam& Param, const MkString& AppName)
{
    m_AppName = AppName;
    return CMkGb28181::Start(Param, [this](const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb) {
        return OnGbRequest(pGbReq, Cb);
    });
}

Uint32 CMkGbMediaServer::SetRegisterServer(const MkString& ServerId, const MkString& ServerRealm, const MkString& ServerHost, Uint16 Port, BOOL bTcpSip, const MkString& UserName, const MkString& Password, Uint32 Expires, Uint32 HbInterval, Uint32 HbCount)
{
    m_RegServerId = ServerId;
    m_RegServerRealm = ServerRealm;
    m_RegServerUserName = UserName;
    m_RegServerPassword = Password;
    m_RegExpires = Expires;
    m_HbCount = HbCount;
    m_HbInterval = HbInterval;
    m_RegHost = ServerHost;
    m_RegPort = Port;
    m_RegTcpSip = bTcpSip;
    AddRouter(ServerId, ServerRealm, ServerHost, Port, bTcpSip);
    CMkGbDeviceAuthorRequest Req;
    Req.m_RouterId = ServerId;
    Req.m_DstId = ServerId;
    Req.m_Realm = ServerRealm;
    Req.m_Expires = Expires;
    return RegisterServer(Req, 0 == Expires);
}

Uint32 CMkGbMediaServer::OnGbRequest(const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    Uint32 ErrorCode = NoneError;
    switch (pGbReq->m_RequestType) {
    case MkGbRequestMessage:
        ErrorCode = OnGbMessageRequest(dynamic_cast<const CMkGbMessageRequest*>(pGbReq), Cb);
        break;
    case MkGbRequestInvite:
        ErrorCode = OnGbInviteReqeust(dynamic_cast<const CMkGbInviteReqeust*>(pGbReq), Cb);
        break;
    case MkGbRequestBye:
        ErrorCode = OnGbByeRequest(dynamic_cast<const CMkGbByeReqeust*>(pGbReq), Cb);
        break;
    case MkGbRequestAck:
        ErrorCode = OnGbAckRequest(dynamic_cast<const CMkGbAckReqeust*>(pGbReq));
    case MkGbReqeustInfo:
        break;
    case MkGbRequestSubscribe:
        ErrorCode = UnSupported;
        break;
    default:
        break;
    }
    return ErrorCode;
}

Uint32 CMkGbMediaServer::OnGbMessageRequest(const CMkGbMessageRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    Uint32 ErrorCode = InvalidParams;
    if (pGbReq
        && "ConfigDownload" == pGbReq->m_CmdType
        && "Query" == pGbReq->m_MessageType) {
        MkMapString::const_iterator it = pGbReq->m_Message.MainParam.find("ConfigType");
        if (it != pGbReq->m_Message.MainParam.end()) {
            CMkGbMessageResponse Res;
            MkGbMessage BasicParam;
            BasicParam.MainParam["Name"] = "mk media server";
            BasicParam.MainParam["Expiration"] = std::to_string(m_RegExpires);
            BasicParam.MainParam["HeartBeatInterval"] = std::to_string(m_HbInterval);
            BasicParam.MainParam["HeartBeatCount"] = std::to_string(m_HbCount);
            Res.m_Message.MapMessage["ConfigType"] = BasicParam;
            Cb(NoneError, &Res);
            ErrorCode = NoneError;
        }
    }
    return ErrorCode;
}

Uint32 CMkGbMediaServer::OnGbInviteReqeust(const CMkGbInviteReqeust* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    MkString SessionId = pGbReq->m_SessionId;
    MkString StreamPath = pGbReq->m_SubjectSource;
    if (StreamPath.empty()) {
        StreamPath = pGbReq->m_DstId;
    } else {
        size_t nPos = StreamPath.find(":0");
        if (MkString::npos != nPos) {
            StreamPath = StreamPath.substr(0, nPos);
        } else {
            CMkUtil::Replace(StreamPath, ":", "_");
        }
    }

    CMkVideoParam VideoParam;
    CMkAudioParam AudioParam;
    Uint32 Duration;
    Uint32 FileSize;
    MkString SourceSession;
    MkString MediaPath = "/" + m_AppName + "/" + StreamPath;
    BOOL bGetSource = NoneError == m_MediaCbs.GetSourceParamCb(MediaPath, VideoParam, AudioParam, Duration, FileSize, SourceSession);

    CMkGbInviteResponse Res;
    MkGbInviteParam InviteParam;
    InviteParam.StreamPath = StreamPath;
    CMkRtp* pRtp = nullptr;
    CMkSdp AnwerSdp;
    CMkSdpMedia AnwerSdpMedia;
    if (!pGbReq->m_OfferSdp.empty()) {
        CMkSdp OfferSdp;
        Uint32 ErrorCode = OfferSdp.ParseContent(pGbReq->m_OfferSdp);
        MkCheckErrorLog(ErrorCode, "offset sdp parse failed\n");
        if (OfferSdp.GetMedia().empty()) {
            return InvalidParams;
        }
        InviteParam.RemoteHost = OfferSdp.GetOrigin().GetAddr();
        if (!OfferSdp.GetConnection().GetAddr().empty()) {
            InviteParam.RemoteHost = OfferSdp.GetConnection().GetAddr();
        }
        CMkSdpMedia OffserSdpMedia = *OfferSdp.GetMedia().begin();
        if (!OffserSdpMedia.GetSdpConnection().GetAddr().empty()) {
            InviteParam.RemoteHost = OffserSdpMedia.GetSdpConnection().GetAddr().empty();
        }
        InviteParam.RemotePort = OffserSdpMedia.GetPort();
        MkString RemoteSsrc;
        OffserSdpMedia.GetExtendValue("y", RemoteSsrc);
        Uint32 uRemoteSsrc = CMkUtil::SafeAtoi(RemoteSsrc);
        if (0 == uRemoteSsrc) {
            uRemoteSsrc = CMkUtil::GetRandomNumber();
        }
        if (OffserSdpMedia.GetFmts().empty()) {
            return InvalidParams;
        }

        CMkSdpFmt UseFmt;
        MkMap<Uint32, CMkSdpFmt>::const_iterator itFmt = OffserSdpMedia.GetFmts().begin();
        for (; itFmt != OffserSdpMedia.GetFmts().end(); itFmt++) {
            //only support ps stream
            if ("PS" == itFmt->second.GetEncodingName()) {
                UseFmt = itFmt->second;
                break;
            }
        }
        if (itFmt == OffserSdpMedia.GetFmts().end()) {
            Cb(MkSipStatusUnsupportedCodec, nullptr);
            return NoneError;
        }
        InviteParam.Payload = UseFmt.GetPayload();
        AnwerSdp.SetOrigin(CMkOrigin(GetSipId(), "0", "0", "IN", "IP4", GetTcpPublicHost()));
        AnwerSdp.SetConnection(CMkSdpConnection("IN", "IP4", GetTcpPublicHost()));
        AnwerSdp.SetVersion("0");
        AnwerSdp.SetSessionName(OfferSdp.GetSessionName());
        AnwerSdp.SetTime(OfferSdp.GetTime());
        AnwerSdpMedia.SetMediaType("video");
        AnwerSdpMedia.AddFmt(UseFmt);
        AnwerSdpMedia.AddExtend("y", std::to_string(uRemoteSsrc));

        MkString SetUpValue;
        MkVector<CMkSdpAttribute>::const_iterator it = OffserSdpMedia.GetAttributes().begin();
        for (; it != OffserSdpMedia.GetAttributes().end(); it++) {
            if ("recvonly" == it->GetField()) {
                InviteParam.bConsumer = TRUE;
                if (!bGetSource) {
                    //not find stream
                    Cb(MkSipStatusNotFound, nullptr);
                    return NoneError;
                }
                AnwerSdpMedia.AddAttr(CMkSdpAttribute("sendonly"));
            }
            if ("sendonly" == it->GetField()) {
                InviteParam.bConsumer = FALSE;
                if (bGetSource) {
                    Cb(MkSipStatusBusyEverywhere, nullptr);
                    return NoneError;
                }
                AnwerSdpMedia.AddAttr(CMkSdpAttribute("recvonly"));
            }
            if ("setup" == it->GetField()) {
                SetUpValue = it->GetValue();
            }
        }

        if ("TCP/RTP/AVP" == OffserSdpMedia.GetProtocol()) {
            if ("active" == SetUpValue) {
                AnwerSdpMedia.AddAttr(CMkSdpAttribute("setup", "passive"));
                CMkRtpTcpServer *pRtpTcpServer = m_pRtpPool->GetFreeTcpServer();
                if (!pRtpTcpServer) {
                    return SystemBusy;
                }
                AnwerSdpMedia.SetPort(pRtpTcpServer->GetLocalPort());
                InviteParam.pUseRtp = pRtpTcpServer;
            } else {
                AnwerSdpMedia.AddAttr(CMkSdpAttribute("setup", "active"));
                CMkRtpTcpClient *pRtpClient = new CMkRtpTcpClient(GetEventPool()->GetFreeEvent(), GetTimer(), [this](CMkTcpClient* pClient) {
                    pClient->DeleteLater();
                });
                pRtpClient->Create(FALSE);
                while (1) {
                    Uint16 Port = CMkUtil::GetRandomNumber() % 0xFFFF;
                    if (NoneError == pRtpClient->Bind(Port)) {
                        AnwerSdpMedia.SetPort(Port);
                        break;
                    }
                }
                InviteParam.pUseRtp = pRtpClient;
            }
            AnwerSdpMedia.AddAttr(CMkSdpAttribute("connection", "new"));
            AnwerSdpMedia.SetProtocol("TCP/RTP/AVP");
        } else {  //udp
            CMkRtpUdpServer *pRtpUdpServer = m_pRtpPool->GetFreeUdpServer();
            AnwerSdpMedia.SetPort(pRtpUdpServer->GetRtpPort());
            AnwerSdpMedia.SetProtocol("RTP/AVP");
            InviteParam.pUseRtp = pRtpUdpServer;
        }
        InviteParam.Ssrc = uRemoteSsrc;
    } else {
        if (bGetSource) {
            Cb(MkSipStatusBusyEverywhere, nullptr);
            return NoneError;
        }
        InviteParam.bConsumer = FALSE;
        char pSsrc[Len16] = { 0 };
        snprintf(pSsrc, Len16, "%04d", CMkUtil::GetRandomNumber() % 10000);
        MkString strSsrc;
        size_t nPos = StreamPath.find(":0");
        if (MkString::npos == nPos) {
            strSsrc = "0";
        } else {
            strSsrc = "1";
        }
        if (StreamPath.size() > 8) {
            strSsrc += StreamPath.substr(3, 5);
        }
        strSsrc += MkString(pSsrc);
        Uint32 uSsrc = std::stoi(strSsrc);
        InviteParam.bNeedAckSdp = TRUE;

        MkPair<CMkRtpTcpServer*, CMkRtpUdpServer*> PairServer = m_pRtpPool->GetFreeRtpServer();
        if (!PairServer.first || !PairServer.second) {
            return SystemBusy;
        }
        InviteParam.pTcpServer = PairServer.first;
        InviteParam.pUdpServer = PairServer.second;
        InviteParam.Payload = 96;
        AnwerSdp.SetOrigin(CMkOrigin(GetSipId(), "0", "0", "IN", "IP4", GetTcpPublicHost()));
        AnwerSdp.SetConnection(CMkSdpConnection("IN", "IP4", GetTcpPublicHost()));
        AnwerSdpMedia.SetPort(PairServer.first->GetLocalPort());
        AnwerSdpMedia.SetProtocol("TCP/RTP/AVP");

        AnwerSdp.SetVersion("0");
        MkString Session;
        CMkUtil::CreateRandomString(Len16, Session);
        AnwerSdp.SetSessionName(Session);
        AnwerSdp.SetTime(CMkSdpTime(0, 0, MkVectorString()));
        AnwerSdpMedia.SetMediaType("video");
        CMkSdpFmt SdpFmt;
        SdpFmt.SetPayload(96);
        SdpFmt.SetEncodingName("PS");
        SdpFmt.SetClockRate(MkDefaultClockRate);
        AnwerSdpMedia.AddFmt(SdpFmt);
        AnwerSdpMedia.AddAttr(CMkSdpAttribute("recvonly"));
        AnwerSdpMedia.AddAttr(CMkSdpAttribute("setup", "passive"));
        AnwerSdpMedia.AddAttr(CMkSdpAttribute("connection", "new"));
        AnwerSdpMedia.AddExtend("y", strSsrc);
    }
    AnwerSdp.AddMedia(AnwerSdpMedia);
    AnwerSdp.ToString(Res.m_AnwserSdp);
    m_InviteLock.Lock();
    m_MapInvite[SessionId] = InviteParam;
    m_InviteLock.Unlock();

    Cb(NoneError, &Res);
    return NoneError;
}

Uint32 CMkGbMediaServer::OnGbAckRequest(const CMkGbAckReqeust* pGbReq)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    Uint32 ErrorCode = InvalidParams;
    MkGbInviteParam InviteParam;
    MkString PlaySession = pGbReq->m_SessionId;
    m_InviteLock.Lock();
    MkMap<MkString, MkGbInviteParam>::iterator it = m_MapInvite.find(PlaySession);
    if (it != m_MapInvite.end()) {
        InviteParam = it->second;
        m_MapInvite.erase(it);
        ErrorCode = NoneError;
    }
    m_InviteLock.Unlock();
    if (NoneError != ErrorCode) {
        MkErrorLog("invalid ack\n");
        return InvalidParams;
    }

    if (InviteParam.bNeedAckSdp && pGbReq->m_RemoteSdp.empty()) {
        MkErrorLog("ack need sdp but this not has\n");
        return InvalidParams;
    }

    if (InviteParam.bConsumer) {
        //all the consumer not need sdp
        CMkVideoParam VideoParam;
        CMkAudioParam AudioParam;
        Uint32 Duration;
        Uint32 FileSize;
        MkString SourceSession;

        if (m_MediaCbs.GetSourceParamCb) {
            ErrorCode = m_MediaCbs.GetSourceParamCb("/" + m_AppName + "/" + InviteParam.StreamPath, VideoParam, AudioParam, Duration, FileSize, SourceSession);
        }
        if (NoneError == ErrorCode) {
            MkRtpRemoter Remoter;
            Remoter.RtpPacketCb = nullptr;
            Remoter.RtcpPacketCb = [this](const CMkRtcpPacket& RtcpPacket, const MkString& Host, Uint16 Port) {
                return OnRtcpPacket(nullptr, RtcpPacket, Host, Port);
            };
            Remoter.RtpClosedCb = [this, PlaySession, SourceSession]() {
                if (m_MediaCbs.ConsumerClosedCb) {
                    m_MediaCbs.ConsumerClosedCb(SourceSession, MkMediaConsumeGb, PlaySession);
                }
                m_GbConsumerLock.Lock();
                MkMap<MkString, CMkGbConsumer*>::iterator it = m_MapGbConsumer.find(PlaySession);
                if (it != m_MapGbConsumer.end()) {
                    MkDelete(it->second);
                    m_MapGbConsumer.erase(it);
                }
                m_GbConsumerLock.Unlock();
            };
            Remoter.RtpRemoteHost = InviteParam.RemoteHost;
            Remoter.RtpRemotePort = InviteParam.RemotePort;
            Remoter.RtpType = MkRtpRecver;
            Remoter.Payload = InviteParam.Payload;
            Remoter.Ssrc = InviteParam.Ssrc;
            InviteParam.pUseRtp->AddRtpRemoter(InviteParam.Ssrc, Remoter);
            CMkGbConsumer * pConsumer = new CMkGbConsumer(InviteParam.Ssrc, InviteParam.pUseRtp);
            pConsumer->SetConsumerId(PlaySession);
            m_GbConsumerLock.Lock();
            m_MapGbConsumer[PlaySession] = pConsumer;
            m_GbConsumerLock.Unlock();
            ErrorCode = m_MediaCbs.ConsumerAddCb(SourceSession, new CMkGbConsume, pConsumer);
        }
    } else {
        if (!pGbReq->m_RemoteSdp.empty()) {
            CMkSdp Sdp;
            BOOL bTcpRtp = FALSE;
            Uint32 Ssrc = 0;
            Sdp.ParseContent(pGbReq->m_RemoteSdp);
            InviteParam.RemoteHost = Sdp.GetOrigin().GetAddr();
            if (!Sdp.GetConnection().GetAddr().empty()) {
                InviteParam.RemoteHost = Sdp.GetConnection().GetAddr();
            }
            if (Sdp.GetMedia().empty()) {
                return InvalidParams;
            }
            CMkSdpMedia SdpMedia = *Sdp.GetMedia().begin();
            if (!SdpMedia.GetSdpConnection().GetAddr().empty()) {
                InviteParam.RemoteHost = SdpMedia.GetSdpConnection().GetAddr();
            }
            InviteParam.RemotePort = SdpMedia.GetPort();
            if (SdpMedia.GetFmts().empty()) {
                return InvalidParams;
            }
            CMkSdpFmt UseFmt;
            MkMap<Uint32, CMkSdpFmt>::const_iterator itFmt = SdpMedia.GetFmts().begin();
            for (; itFmt != SdpMedia.GetFmts().end(); itFmt++) {
                //only support ps stream
                if ("PS" == itFmt->second.GetEncodingName()) {
                    UseFmt = itFmt->second;
                    break;
                }
            }
            if (itFmt == SdpMedia.GetFmts().end()) {
                return InvalidParams;
            }
            InviteParam.Payload = UseFmt.GetPayload();
            BOOL bRemoteSendOnly = FALSE;
            MkVector<CMkSdpAttribute>::const_iterator itAttr = SdpMedia.GetAttributes().begin();
            for (; itAttr != SdpMedia.GetAttributes().end(); itAttr++) {
                if ("setup" == itAttr->GetField() && "active" != itAttr->GetValue()) {
                    return InvalidParams;
                }
                if ("sendonly" == itAttr->GetField()) {
                    bRemoteSendOnly = TRUE;
                }
            }
            if (FALSE == bRemoteSendOnly) {
                return InvalidParams;
            }

            InviteParam.pUseRtp = InviteParam.pUdpServer;
            if ("TCP/RTP/AVP" == SdpMedia.GetProtocol()) {
                bTcpRtp = TRUE;
                InviteParam.pUseRtp = InviteParam.pTcpServer;
            }

            MkString strSsrc;
            SdpMedia.GetExtendValue("y", strSsrc);
            Ssrc = CMkUtil::SafeAtoi(strSsrc);
            //can't set ssrc 0
            if (0 == Ssrc) {
                return InvalidParams;
            }
            InviteParam.Ssrc = Ssrc;
        }

        CMkGbStreamSource* pMediaSource = new CMkGbStreamSource(InviteParam.pUseRtp, InviteParam.Ssrc, [this, PlaySession]() {
            //stream sender delay 2 sec to send bye
            MkString Delayer;
            GetTimer()->AddDelayer([this, PlaySession]() {
                ByeRequest(PlaySession, nullptr);
                if (m_MediaCbs.SourceDeleteCb) {
                    m_MediaCbs.SourceDeleteCb(PlaySession);
                }
            }, 2000, Delayer);
        });

        MkRtpRemoter Remoter;
        Remoter.RtpPacketCb = [this, pMediaSource](const CMkRtpPacket& RtpPacket, const MkString& Host, Uint16 Port) {
            return OnRtpPacket(pMediaSource, RtpPacket, Host, Port);
        };
        Remoter.RtcpPacketCb = [this, pMediaSource](const CMkRtcpPacket& RtcpPacket, const MkString& Host, Uint16 Port) {
            return OnRtcpPacket(pMediaSource, RtcpPacket, Host, Port);
        };
        Remoter.RtpClosedCb = [this, PlaySession]() {
            //stream sender delay 2 sec to send bye
            MkString Delayer;
            GetTimer()->AddDelayer([this, PlaySession]() {
                ByeRequest(PlaySession, nullptr);
                if (m_MediaCbs.SourceDeleteCb) {
                    m_MediaCbs.SourceDeleteCb(PlaySession);
                }
            }, 2000, Delayer);
        };

        Remoter.RtpRemoteHost = InviteParam.RemoteHost;
        Remoter.RtpRemotePort = InviteParam.RemotePort;
        Remoter.RtpType = MkRtpRecver;
        Remoter.Payload = InviteParam.Payload;
        Remoter.Ssrc = InviteParam.Ssrc;
        pMediaSource->SetAppName(m_AppName);
        pMediaSource->SetSession(PlaySession);
        pMediaSource->SetStreamPath(InviteParam.StreamPath);
        InviteParam.pUseRtp->AddRtpRemoter(InviteParam.Ssrc, Remoter);
        if (m_MediaCbs.SourceAddCb) {
            ErrorCode = m_MediaCbs.SourceAddCb(pMediaSource);
        }
    }
    CMkRtpTcpClient* pClient = dynamic_cast<CMkRtpTcpClient*>(InviteParam.pUseRtp);
    if (pClient) {
        pClient->Connect(InviteParam.RemoteHost, InviteParam.RemotePort);
    }
    return ErrorCode;
}

Uint32 CMkGbMediaServer::OnGbByeRequest(const CMkGbByeReqeust* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    Cb(NoneError, nullptr);
    if (!m_MediaCbs.SourceDeleteCb
        || NoneError != m_MediaCbs.SourceDeleteCb(pGbReq->m_SessionId)) {
        m_MediaCbs.ConsumerClosedCb("", MkMediaConsumeGb, pGbReq->m_SessionId);
    }
    return NoneError;
}

Uint32 CMkGbMediaServer::RegisterServer(const CMkGbDeviceAuthorRequest& Req, BOOL bFailEnd/* = FALSE*/)
{
    return RegisterRequest(Req, [this, Req, bFailEnd](Uint32 ErrorCode, const CMkGbResponse* pResponse) {
        const CMkGbDeviceAuthorResponse *pRes = dynamic_cast<const CMkGbDeviceAuthorResponse*>(pResponse);
        if (MkSipStatusRequestTimeout + SipResponseErrorBegin == ErrorCode && 0 == Req.m_Expires) {
            DeleteRouter(Req.m_RouterId);
        }
        if (MkSipStatusUnauthorized + SipResponseErrorBegin == ErrorCode && pRes) {
            MkString Uri = "sip:" + m_RegServerId + "@" + m_RegServerRealm;
            MkString Realm = pRes->m_Realm.substr(1, pRes->m_Realm.size() - 2);
            MkString Nonce = pRes->m_Nonce.substr(1, pRes->m_Nonce.size() - 2);

            if ("MD5" == pRes->m_Algorithm) {
                MkString Ha1 = CMkMd5Encode::Encode(m_RegServerUserName + ":" + Realm + ":" + m_RegServerPassword);
                MkString Ha2 = CMkMd5Encode::Encode("REGISTER:" + Uri);
                MkString Ha3 = CMkMd5Encode::Encode(Ha1 + ":" + Nonce + ":" + Ha2);
                CMkGbDeviceAuthorRequest ReReq;
                ReReq.m_AuthorType = pRes->m_AuthType;
                ReReq.m_UserName = m_RegServerUserName;
                ReReq.m_Algorithm = pRes->m_Algorithm;
                ReReq.m_Expires = Req.m_Expires;
                ReReq.m_Realm = Realm;
                ReReq.m_Nonce = Nonce;
                ReReq.m_RouterId = m_RegServerId;
                ReReq.m_Response = Ha3;
                ReReq.m_Uri = "\"" + Uri + "\"";
                ReReq.m_DstId = m_RegServerId;
                ReReq.m_RegisterId = pRes->m_RegisterId;
                RegisterServer(ReReq);
            } else {
                ErrorCode = InvalidParams;
            }
        } else if (NoneError == ErrorCode) {
            if (0 == Req.m_Expires) {
                DeleteRouter(Req.m_RouterId);
            } else {
                m_LastActiveTime = NowMkTime;
                m_RegSuccess = TRUE;
                if (m_RegStateChangeCb) {
                    m_RegStateChangeCb();
                }
                KeepAliveServer();
                GetTimer()->AddTimer([this]() {
                    KeepAliveServer();
                }, m_HbInterval * 1000, m_KeepAliverTimer);
            }
        } else {
            if (!bFailEnd) {
                GetTimer()->AddDelayer([this, Req]() {
                    RegisterServer(Req);
                }, 5 * 1000, m_RegisterDelayer);
            }
        }
    });
}

Uint32 CMkGbMediaServer::KeepAliveServer()
{
    CMkGbMessageRequest Req;
    Req.m_RouterId = m_RegServerId;
    Req.m_DstId = m_RegServerId;
    Req.m_DeviceId = GetSipId();
    Req.m_CmdType = "Keepalive";
    Req.m_MessageType = "Notify";
    return MessageRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        if (NoneError == ErrorCode) {
            m_LastActiveTime = NowMkTime;
            return;
        }
        if (NowMkTime.OffsetSec(m_LastActiveTime) > (int)(m_HbInterval*m_HbCount)) {
            m_RegSuccess = FALSE;
            if (m_RegStateChangeCb) {
                m_RegStateChangeCb();
            }
            GetTimer()->AddDelayer([this]() {
                CMkGbDeviceAuthorRequest Req;
                Req.m_RouterId = m_RegServerId;
                Req.m_DstId = m_RegServerId;
                Req.m_Realm = m_RegServerRealm;
                Req.m_Expires = m_RegExpires;
                RegisterServer(Req);
            }, 5 * 1000, m_RegisterDelayer);
        }
    });
}

Uint32 CMkGbMediaServer::OnRtpPacket(CMkGbStreamSource* pMediaSource, const CMkRtpPacket& RtpPacket, const MkString& Host, Uint16 Port)
{
    return pMediaSource->InputDataSlice(RtpPacket.GetPayloadData(), RtpPacket.GetPayloadLength(), RtpPacket.GetTimeStamp(), RtpPacket.GetMaker());
}

Uint32 CMkGbMediaServer::OnRtcpPacket(CMkGbStreamSource* pMediaSource, const CMkRtcpPacket& RtcpPacket, const MkString& Host, Uint16 Port)
{
    switch (RtcpPacket.GetPayload()) {
    case MkRtcpBye:
        break;
    default:
        break;
    }
    return NoneError;
}

CMkGbMediaServer::~CMkGbMediaServer()
{
    m_GbConsumerLock.Lock();
    MkMap<MkString, CMkGbConsumer*>::iterator it = m_MapGbConsumer.begin();
    for (; it != m_MapGbConsumer.end(); it++) {
        MkDelete(it->second);
    }
    m_MapGbConsumer.clear();
    m_GbConsumerLock.Unlock();
}